﻿using System;
using System.Reflection;
using MugenInjection.Delegates;
using MugenInjection.Infrastructure;

namespace MugenInjection.Parameters
{
    /// <summary>
    ///     Represents the value of a constructor argument.
    /// </summary>
    public class ConstructorParameter : InjectionParameter
    {
        #region Constructors

        /// <summary>
        ///     Initializes a new instance of the <see cref="ConstructorParameter" /> class.
        /// </summary>
        public ConstructorParameter(string name, ParameterDelegate<object> getValueDelegate, Type type = null)
            : base(MemberTypes.Constructor, name, getValueDelegate)
        {
            // ReSharper disable DoNotCallOverridableMethodsInConstructor
            ParameterType = type;
            // ReSharper restore DoNotCallOverridableMethodsInConstructor
        }

        /// <summary>
        ///     Initializes a new instance of the <see cref="ConstructorParameter" /> class.
        /// </summary>
        public ConstructorParameter(string name, object value)
            : base(MemberTypes.Constructor, name, value)
        {
        }

        /// <summary>
        ///     Initializes a new instance of the <see cref="ConstructorParameter" /> class.
        /// </summary>
        public ConstructorParameter(string name, Type parameterType, object value)
            : base(MemberTypes.Constructor, name, value)
        {
            Validate.ArgumentNotNull(parameterType, "parameterType");
            // ReSharper disable DoNotCallOverridableMethodsInConstructor
            ParameterType = parameterType;
            // ReSharper restore DoNotCallOverridableMethodsInConstructor
        }

        /// <summary>
        ///     Initializes a new instance of the <see cref="ConstructorParameter" /> class.
        /// </summary>
        public ConstructorParameter(int parameterPosition, ParameterDelegate<object> getValueDelegate, Type type = null)
            : base(MemberTypes.Constructor, EmptyParameterName, getValueDelegate)
        {
            Position = parameterPosition;
            // ReSharper disable DoNotCallOverridableMethodsInConstructor
            ParameterType = type;
            // ReSharper restore DoNotCallOverridableMethodsInConstructor
        }

        /// <summary>
        ///     Initializes a new instance of the <see cref="ConstructorParameter" /> class.
        /// </summary>
        public ConstructorParameter(int parameterPosition, object value)
            : base(MemberTypes.Constructor, EmptyParameterName, value)
        {
            Position = parameterPosition;
        }

        /// <summary>
        ///     Initializes a new instance of the <see cref="ConstructorParameter" /> class.
        /// </summary>
        public ConstructorParameter(int parameterPosition, Type parameterType, object value)
            : base(MemberTypes.Constructor, EmptyParameterName, value)
        {
            Validate.ArgumentNotNull(parameterType, "parameterType");
            Position = parameterPosition;
            // ReSharper disable DoNotCallOverridableMethodsInConstructor
            ParameterType = parameterType;
            // ReSharper restore DoNotCallOverridableMethodsInConstructor
        }

        #endregion

        #region Properties

        /// <summary>
        ///     Gets the position of parameter, if any.
        /// </summary>
        public int? Position { get; private set; }

        #endregion

        #region Override

        /// <summary>
        ///     Determines whether the specified request can be resolved.
        /// </summary>
        /// <param name="memberInfo">
        ///     The specified <see cref="MemberInfo" />
        /// </param>
        /// <param name="parameter">
        ///     The specified <see cref="ParameterInfo" />
        /// </param>
        /// <returns>
        ///     <c>True</c> if the specified request has been resolved; otherwise, <c>false</c>.
        /// </returns>
        protected override bool CanResolveInternal(MemberInfo memberInfo, ParameterInfo parameter)
        {
            if (parameter == null || !IsAssignableParameter(parameter.ParameterType))
                return false;
            int? position = Position;
            if (position.HasValue)
                return parameter.Position == position.Value;
            return parameter.Name.Equals(Name);
        }

        #endregion
    }
}